<?php




namespace app\api\logic;

use think\Db;
use think\Exception;
use think\Log;
use app\common\library\enum\OrderStatusEnum;

class Notify extends BaseApi
{

    /**
     * 支付回调助手
     *
     * @param $data
     * @return bool
     *
     */
    public function handle($data){
        try{
            //获取支付订单号
            //查找订单
            $order = $this->modelOrders->where($data)->lock(true)->find();
            //超时判断 （超时10分钟当作失败订单）  判断状态

            if (!$this->callback($order)) {

                //修改订单状态为支付成功，回调失败
                $this->modelOrders->changeOrderStatusValue([
                    'status'  => OrderStatusEnum::PAID_CALLBACK_ERR
                ], [
                    'id'=>$order->id
                ]);

                return false;
            }
            
            //状态待支付、回调失败
            if (in_array($order->status, [OrderStatusEnum::UNPAID, OrderStatusEnum::PAID_CALLBACK_ERR])) {
                $this->updateOrderInfo($order, true);
            }

            return true;

        } catch (Exception $ex) {
            return false;
        }

    }

    public  static function curl($url, $data)
    {

        header("Content-type: text/html; charset=utf-8");
        $curl = curl_init();
        //设置抓取的url
        curl_setopt($curl, CURLOPT_URL, $url);
        //设置获取的信息以文件流的形式返回，而不是直接输出。
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        //设置头文件的信息作为数据流输出
        curl_setopt($curl, CURLOPT_HEADER, 0);
        curl_setopt($curl,CURLOPT_CONNECTTIMEOUT,10);
        // 告诉curl禁用ssl当中的公用名,公用名只有两种值0表没有，1表示拥有，默认为1
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
        //设置post方式提交
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        //为没有ssl所有不要进行认证的校验
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_HTTPHEADER, array(
                'Content-Type: application/json; charset=utf-8',
                'Content-Length: ' . strlen($data))
        );
        json_encode($data, JSON_UNESCAPED_UNICODE); //解决json处理传送中文问题
        //执行命令
        $str = curl_exec($curl);
        Log::write("Notify Curl Request:\n\nURL: $url\n\nParams:\n$data\n\nResult:\n$str");
        //关闭URL请求
        curl_close($curl);
        //把请求的数据进行返回
        return $str;
    }


    public function callback($order) {

        $params = [
            'app_id' => $order->uid,
            'extends' => $order->extra,
            'order_id' => $order->out_trade_no,
            'pay_amt' => $order->amount,
            'pay_result' => 1,
            'pay_seq' => $order->trade_no,
            'time_stamp' => date("YmdHis", $order->update_time),
        ];

        $appKeys = (array)$this->logicApi->getAppKeyMap('uid,key', 'uid');
        $key = $appKeys[$order->uid];
        $params['sign'] = $this->makeSign($params, $key);
        $url = urldecode($order['notify_url']);
        if (strpos($url, "http") !== 0) {
            //不是http开头的正常的URL直接返回成功
            return true;
        }

        $result = self::curl($url, json_encode($params));
        return (strtolower(trim($result)) == 'ok') ? true : false;
    }


    public function makeSign($params, $key) {
        ksort($params);
        $str = '';
        foreach ($params as $k => $v) {
            $str .= "{$k}={$v}&";
        }
        
        $str .= "key={$key}";

        return md5($str);
    }

    /**
     * 更新支付订单数据
     *
     *
     * @param $order
     * @param $success
     */
    private function updateOrderInfo($order, $success)
    {

        /*************订单操作************/
        //1.查找用户对应渠道费率
        $account = $this->logicPay->getAccountInfo(['id' => $order->cnl_id]);

        $profit = $this->logicUser->getUserProfitInfo(['uid' => $order->uid, 'cnl_id' => $account->cnl_id]);
        if(empty($profit)) $profit = $account;

        //2.数据计算
        //实付金额 - 扣除渠道费率后
        // $income =  bcsub($order->amount , bcmul($order->amount,$account['rate'],2),  2);

        //income是订单收入, 不需要计算费率
        $income = $order->amount;

        $agent_in = "0.00";
        //商户收入
        $user_in =bcmul($income, $profit['urate'], 2);
        //是否有代理
        if ($order->puid != 0){
            //1.获取代理的费率
            $agent_profit = $this->logicUser->getUserProfitInfo(['uid' => $order->puid, 'cnl_id' => $account->cnl_id]);
            //2.代理收入
            $agent_in = bcsub($income, bcmul($income, $agent_profit['urate'], 2), 2);
            //3.商户收入
            $user_in = bcmul($income, bcmul($agent_profit['urate'], $profit['urate'], 2), 2);
            /*************写入商户代理资金******************/
            //支付成功  写入结算金额
            $this->logicBalanceChange->creatBalanceChange($order->puid,$agent_in,'商户单号'. $order->out_trade_no . '支付成功，代理分润金额转入','enable',false);
            /**************写入商户代理资金结束*****************/
        }
        /*************写入商户资金******************/
        //支付成功  扣除待支付金额 (这个操作就只有两个地方   自动关闭订单和这里)
        $this->logicBalanceChange->creatBalanceChange($order->uid,$user_in,'单号'. $order->out_trade_no . '支付成功，收入至待结算金额','disable',false);
        /**************写入商户资金结束*****************/
        //平台收入
        $platform_in = bcsub($income, bcadd($user_in, $agent_in, 2), 2);
        //3.数据存储
        $this->modelOrders->changeOrderStatusValue([
            'income'    => $income,
            'user_in'    => $user_in,
            'agent_in'    => $agent_in,
            'platform_in'    => $platform_in,
            'status'  => $success ? OrderStatusEnum::PAID : OrderStatusEnum::UNPAID
        ], [
            'id'=>$order->id
        ]);
    }

    /**
     * 自动修复回调失败的订单
     */
    public function autoCallbackOrders()
    {
        $where = [
            'create_time' => ['gt', time() - 36000],
            'status' => OrderStatusEnum::PAID_CALLBACK_ERR
        ];
        $data = $this->logicOrders->getOrderList($where,true, 'create_time desc',false);
        foreach($data as $item){
            $this->handle(['id' => $item['id']]);
        }
    }
}
